<!-- 请假 -->
<template>
  <el-dialog v-model="dialogVisible" :title="'申请' + dialogTitle" width="524" draggable @closed="handlerClosed">
    <div v-if="!isCheckedCategory">
      <el-space wrap>
        <el-button v-for="item in holidayCategoryList" class="btn-category" @click="handleClickBtnCategory(item)">
          <div class="cell">
            <div class="icon">
              <el-icon size="48px"><component :is="iconItem[item.dictValue]" /></el-icon>
            </div>
            <div class="text">{{ item.dictLabel }}</div>
          </div>
        </el-button>
      </el-space>
    </div>
    <div v-else>
      <el-form ref="ruleFormRef" :model="dailogform" :rules="dialogRules" label-width="90px">
        <el-form-item label="日期" size="large"> {{ dailogform.leaveDate }} </el-form-item>
        <el-row :gutter="20">
          <el-col :span="12">
            <el-form-item label="姓名" size="large">
              <el-input v-model="dailogform.userNick" readonly size="large" />
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="部门" size="large">
              <el-input v-model="dailogform.deptName" readonly size="large" />
            </el-form-item>
          </el-col>
        </el-row>
        <el-row :gutter="20" v-if="false">
          <el-col :span="12">
            <el-form-item label="工号" size="large">
              <el-input v-model="dailogform.number" readonly size="large" />
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="岗位" size="large">
              <el-input v-model="dailogform.post" readonly size="large" />
            </el-form-item>
          </el-col>
        </el-row>
        <el-form-item label="请假类型" size="large">
          <el-select v-model="dailogform.leaveCategory" size="large" disabled>
            <el-option v-for="(item, idx) in holidayCategoryList" :key="idx" :value="item.dictValue" :label="item.dictLabel"></el-option>
          </el-select>
        </el-form-item>
        <LeaveTimePicker v-model="leaveApplyDate" :leave-category="dailogform.leaveCategory" />
        <el-form-item label="共计" prop="durationTime">
          <div style="display: flex; width: 100%">
            <el-input v-model="dailogform.durationTime" readonly style="width: 130px">
              <template #append>天</template>
            </el-input>
            <div v-if="flag2" style="flex: 1; margin-left: 12px; text-align: left; line-height: 1; font-size: 12px">
              <el-text type="danger">{{ flag2ErrorMessage }}</el-text>
            </div>
          </div>
        </el-form-item>
        <el-form-item v-show="false" label="开始时间" size="large" prop="startTime">
          <el-date-picker v-model="dailogform.startTime" type="datetime" placeholder="开始时间" format="YYYY-MM-DD HH:mm" date-format="YYYY-MM-DD" time-format="HH:mm" />
        </el-form-item>
        <el-form-item v-show="false" label="结束时间" size="large" prop="endTime">
          <el-date-picker v-model="dailogform.endTime" type="datetime" placeholder="结束时间" format="YYYY-MM-DD HH:mm" date-format="YYYY-MM-DD" time-format="HH:mm" />
        </el-form-item>
        <el-form-item label="请假事由" size="large" prop="reason">
          <el-input v-model="dailogform.reason" style="width: 100%" :autosize="{ minRows: 4, maxRows: 8 }" type="textarea" placeholder="" />
        </el-form-item>
        <el-form-item label="审批流程" size="large" prop="approvalUsers">
          <ApprovalProcessSteps :days="dailogform.durationTime" :user-identity="userIdentity" :start-work-time="userStartWorkTime" v-model="dailogform.approvalUsers" />
        </el-form-item>
        <el-form-item label="" size="small" v-if="dailogform.leaveCategory == '2'">
          <el-space direction="vertical" fill>
            <el-alert title="月度累计时长超过 5 天，需要提交书面说明。" type="error" effect="dark" show-icon :closable="false" />
            <el-alert title="年度累计时长超过 10 天，需要提交书面说明。" type="error" effect="dark" show-icon :closable="false" />
          </el-space>
        </el-form-item>
        <el-form-item label="" size="small" v-else-if="dailogform.leaveCategory == '3'">
          <el-space direction="vertical" fill>
            <el-alert title="年度累计时长超过 15 天，需要提交书面说明。" type="error" effect="dark" show-icon :closable="false" />
          </el-space>
        </el-form-item>
      </el-form>
    </div>
    <template #footer v-if="isCheckedCategory">
      <div class="dialog-footer">
        <el-button @click="handlerClickBtnCancel">取消</el-button>
        <el-button type="primary" @click="handlerClickBtnSubmit(ruleFormRef)">提交</el-button>
      </div>
    </template>
  </el-dialog>
</template>
<script lang="ts" setup>
import { ref, reactive, onMounted, watch } from 'vue'
import { formatDate, calculateWorkingDays, countWeekendAndLegalDays, getWorkdayDates } from '../../utils'
import { useUsersStore, useHolidayCategoryStore, useLegalStore } from '../../stores'
import http from '../../http'
import { userRole, ResultMessage } from '../../utils'
import LeaveTimePicker from '../../components/FormParts/LeaveTimePicker/Index.vue'
import { ElMessage } from 'element-plus'
import type { FormInstance } from 'element-plus'
import iconItemList from '../../global/iconItem'
import ApprovalProcessSteps from '../UserSelf/ApprovalProcessSteps.vue'
import api from '../../api'

const holidayCategoryList = useHolidayCategoryStore().getAllState()
const iconItem = iconItemList
const emits = defineEmits(['submitSuccessed'])
const dialogVisible = ref(false)
const isCheckedCategory = ref(false)
const dialogTitle = ref('请假')
const currentUser = useUsersStore().getAllState()
const userIdentity = ref(-1) // 用户身份
const ruleFormRef = ref<FormInstance>()
const userStartWorkTime = ref('') // 用户身份

const leaveApplyDate = ref()
const flag1 = ref(false)
const flag1ErrorMessage = ref('')
const flag2 = ref(false)
const flag2ErrorMessage = ref('')
const isShowMessage = ref<any>(null)

const defaultDate = new Date()
const dailogform = reactive({
  id: null,
  userId: -1,
  userName: '',
  userNick: '',
  number: '',
  deptId: '',
  deptName: '',
  post: '',
  leaveDate: formatDate(defaultDate, 'yyyy-MM-dd'),
  leaveCategory: '',
  createBy: null,
  createTime: null,
  updateBy: null,
  updateTime: null,
  startTime: ref<Date | null>(null),
  endTime: ref<Date | null>(null),
  durationTime: 0, // 请假时长（小时）
  reason: '',
  approvalUsers: [] as any[],
  leaveDatas: [] as any[],
})

const validateEndTime = (_: any, value: Date, callback: Function) => {
  if (!value) {
    callback(new Error('请输入结束时间'))
  } else if (dailogform.startTime && new Date(value).getTime() <= new Date(dailogform.startTime).getTime()) {
    callback(new Error('结束时间必须大于开始时间'))
  } else {
    callback()
  }
}
const validateLeaveApplyDate = (_: any, value: Date, callback: Function) => {
  if (!value) {
    callback(new Error('请选择请假日期'))
  } else {
    callback()
  }
}

const dialogRules = reactive({
  leaveApplyDate: [{ validator: validateLeaveApplyDate, trigger: ['change', 'blur'] }],
  leaveCategory: [{ required: true, message: '请输入请假类型', trigger: ['change', 'blur'] }],
  startTime: [{ required: true, message: '请输入开始时间', trigger: ['change', 'blur'] }],
  endTime: [
    { required: true, message: '请输入结束时间', trigger: ['change', 'blur'] },
    { validator: validateEndTime, trigger: ['change', 'blur'] },
  ],
  reason: [{ required: true, message: '请输入请假事由', trigger: ['change', 'blur'] }],
  approvalUsers: [
    {
      required: true,
      validator: (_: any, value: any[], callback: Function) => {
        if (value.length === 0) {
          callback(new Error('请选择审批流程'))
        } else if (value.some((item) => item === null)) {
          callback(new Error('审批流程中不能包含空值'))
        } else {
          callback()
        }
      },
      trigger: ['change', 'blur'],
    },
  ],
  durationTime: [
    {
      validator: async (_: any, value: number, callback: Function) => {
        if (value == 0) {
          callback(new Error('请假时长必须大于 0'))
        } else if (value > 15) {
          callback(new Error('连续请假不能超过15天！需要提供书面文件。'))
        } else if (flag1.value) {
          callback(new Error(flag1ErrorMessage.value))
        } else {
          callback()
        }
      },
      trigger: ['change', 'blur'],
    },
  ],
})

/**
 * 打开对话框函数
 *
 * @param objectValue 包含日期、默认打卡分类和是否为比较模式的对象
 */
const openDialog = async (date: Date, leaveCategoryVal: any = null) => {
  flag1.value = false
  flag2.value = false
  flag1ErrorMessage.value = ''
  flag2ErrorMessage.value = ''
  isShowMessage.value = false
  dailogform.durationTime = 1
  // 确认用户身份信息
  const { roles, deptId, startWorkTime, city } = useUsersStore().user as any
  userStartWorkTime.value = startWorkTime

  userIdentity.value = userRole(city, roles, deptId)

  dailogform.approvalUsers = []
  isCheckedCategory.value = false
  if (leaveCategoryVal !== null && leaveCategoryVal !== undefined) {
    dialogTitle.value = leaveCategoryVal.dictLabel
    dailogform.leaveCategory = leaveCategoryVal.dictValue
    isCheckedCategory.value = true
  }

  // 重置isCheckedCategory.value为false
  // 获取当前用户信息
  if (currentUser) {
    // 设置dailogform的userId为当前用户的userId，如果没有则设为-1
    dailogform.userId = currentUser.userId || -1
    // 设置dailogform的deptId为当前用户的deptId，如果没有则设为空字符串
    dailogform.deptId = currentUser.deptId || ''
    // 设置dailogform的deptName为当前用户的deptName，如果没有则设为空字符串
    dailogform.deptName = currentUser.deptName || ''
    // 设置dailogform的userName为当前用户的username，如果没有则设为空字符串
    dailogform.userName = currentUser.username || ''
    // 设置dailogform的userNick为当前用户的nickName，如果没有则设为空字符串
    dailogform.userNick = currentUser.nickName || ''
    // 再次设置dailogform的deptName为当前用户的deptName，如果没有则设为空字符串（此处存在重复赋值）
    dailogform.deptName = currentUser.deptName || ''
  }
  // 将objectValue.date格式化为'yyyy-MM-dd'格式并赋值给dailogform.leaveDate
  dailogform.leaveDate = formatDate(date, 'yyyy-MM-dd')
  // 重置dailogform的startTime为null
  dailogform.startTime = null
  // 重置dailogform的endTime为null
  dailogform.endTime = null
  // 重置dailogform的remark为空字符串
  dailogform.reason = ''

  leaveApplyDate.value = null
  // 显示对话框
  dialogVisible.value = true
}

/**
 * 提交请假申请按钮点击事件处理函数
 *
 * @returns 异步处理函数
 */
const handlerClickBtnSubmit = async (formEl: FormInstance | undefined) => {
  // console.log('dailogform', dailogform)
  if (!formEl) return
  await formEl.validate(async (valid: any) => {
    if (!leaveApplyDate.value) {
      ElMessage.error('请选择请假时间')
      // const { startTime, endTime, leaveDuration } = leaveApplyDate.value
      // console.log('startTime', startTime)
      // console.log('endTime', endTime)
      // console.log('leaveDuration', leaveDuration)
    }
    // console.log('dailogform.startTime', dailogform.startTime)
    if (valid && leaveApplyDate.value && !flag1.value) {
      const paramsTemp = {
        ...dailogform,
        leaveCategory: dailogform.leaveCategory,
        leaveDate: formatDate(new Date(dailogform.leaveDate), 'yyyy-MM-dd'),
        startTime: dailogform.startTime ? formatDate(dailogform.startTime, 'yyyy-MM-dd HH:mm:ss') : null,
        endTime: dailogform.endTime ? formatDate(dailogform.endTime, 'yyyy-MM-dd HH:mm:ss') : null,
      }
      // 安全地删除 startTime 和 endTime 属性
      const { ...rest } = paramsTemp
      const params = rest

      const leaveUser = {
        userId: dailogform.userId,
        userName: dailogform.userName,
        userNick: dailogform.userNick,
      }
      // 处理审批流程数据
      const removeRes = await api.Leave.removeProcessData({ userId: leaveUser.userId, userName: leaveUser.userName })

      // console.log('removeRes', removeRes)
      if (removeRes.code !== 200) {
        ElMessage.error(removeRes.msg)
        return
      }

      // console.log('dailogform.approvalUsers', dailogform.approvalUsers)
      let order = 0
      const addProcessAll: any[] = []
      dailogform.approvalUsers.forEach((item: any) => {
        // console.log('item', item)
        order += 1
        const processUser = {
          processUserId: item.userId,
          processUserName: item.userName,
          processUserNick: item.nickName,
          processOrder: order,
        }
        addProcessAll.push(api.Leave.addProcessData(leaveUser, processUser))
      })
      const promisRes = await Promise.all(addProcessAll)

      const allSuccess = promisRes.every((res) => res.code === 200)

      if (!allSuccess) {
        ElMessage.error('添加审批流程失败')
        return
      }

      // console.log('params', params)
      const res = await http({
        method: 'POST',
        path: '/dev-api/oa/leave',
        params,
      })

      ResultMessage(res.code, '提交请假')
      dialogVisible.value = false
      emits('submitSuccessed')
    }
  })
}

/**
 * 当关闭处理程序时触发的方法
 *
 * 将 isCheckedCategory 的值设置为 false
 */
const handlerClosed = () => {
  isCheckedCategory.value = false
}

/**
 * 重置表单的函数
 *
 * 该函数会重置表单的各个字段到默认值。
 * 首先，它会获取当前用户的信息，并将用户的 ID、部门 ID、部门名称、用户名和用户昵称填充到表单中。
 * 如果没有当前用户信息，则将这些字段设置为默认值。
 * 接着，它会将请假类别字段设置为空字符串，将请假日期字段设置为默认日期，并将开始时间、结束时间和备注字段设置为空。
 */
const formReset = () => {
  const currentUser = useUsersStore().getAllState()
  if (currentUser) {
    dailogform.userId = currentUser.userId || -1
    dailogform.deptId = currentUser.deptId || ''
    dailogform.deptName = currentUser.deptName || ''
    dailogform.userName = currentUser.username || ''
    dailogform.userNick = currentUser.nickName || ''
    dailogform.deptName = currentUser.deptName || ''
  }
  dailogform.leaveCategory = ''
  dailogform.leaveDate = formatDate(defaultDate, 'yyyy-MM-dd')
  dailogform.startTime = null
  dailogform.endTime = null
  dailogform.reason = ''
}
/**
 * 处理点击取消按钮的事件
 */
const handlerClickBtnCancel = () => {
  formReset()
  dialogVisible.value = false
}

/**
 * 处理点击按钮分类的函数
 *
 * @param val 包含分类信息的对象
 */
const handleClickBtnCategory = (val: any) => {
  isCheckedCategory.value = true
  dialogTitle.value = val.dictLabel
  dailogform.leaveCategory = val.dictValue
  /*

    0: 年假： 半天，全天 （上班时间，午餐开始时间，午餐时间结束，下班时间）
    1: 调休假：整小时，半天，全天 （上班时间，午餐开始时间，午餐结束时间，下班时间）
    2: 事假： 一小时 / 半天，全天 （上班时间，午餐开始时间，午餐结束时间，下班时间）
    3: 病假： 半天，全天 （上班时间，午餐开始时间，午餐结束时间，下班时间）

    一小时：0.125
    事假：0.125
    一天：1
    半天：0.5

  */
}

// 监听 leaveApplyDate 的变化，当它有值时执行相关操作

watch(
  () => leaveApplyDate.value,
  async () => {
    if (leaveApplyDate.value) {
      // console.log('leaveApplyDate', leaveApplyDate.value)
      const { startTime, endTime, leaveDuration, hourDuration } = leaveApplyDate.value
      dailogform.leaveDatas = []
      dailogform.approvalUsers = []
      flag1.value = false
      flag1ErrorMessage.value = ''
      flag2.value = false
      flag2ErrorMessage.value = ''

      if (leaveDuration == 1) {
        // 一小时请假
        dailogform.durationTime = 0.125 * hourDuration
        dailogform.leaveDatas = [{ num: dailogform.durationTime, leaveDate: formatDate(new Date(startTime), 'yyyy-MM-dd') }]
      } else if (leaveDuration == 2) {
        // 半天请假
        dailogform.durationTime = 0.5
        dailogform.leaveDatas = [{ num: 0.5, leaveDate: formatDate(new Date(startTime), 'yyyy-MM-dd') }]
      } else if (leaveDuration == 3) {
        // 全天请假
        dailogform.leaveDatas = [{ num: 1, leaveDate: formatDate(new Date(startTime), 'yyyy-MM-dd') }]
        const { total } = countWeekendAndLegalDays(startTime, startTime, useLegalStore().getAllState())
        dailogform.durationTime = 1 - total
      } else {
        // 自定义请假时长
        const { startWorkTime, endWorkTime, startLunchTime, endLunchTime } = currentUser

        const durationTime = calculateWorkingDays(startTime, endTime, startWorkTime, endWorkTime, startLunchTime, endLunchTime)
        const { total } = countWeekendAndLegalDays(startTime, endTime, useLegalStore().getAllState())
        dailogform.leaveDatas = getWorkdayDates(startTime, endTime, startLunchTime, endLunchTime, useLegalStore().getAllState())

        // 计算有效请假时长，减去周末和法定假日的天数，如果结果小于0则设置为0。
        dailogform.durationTime = durationTime - total
        if (dailogform.durationTime < 0) {
          dailogform.durationTime = 0
        }
      }
      // console.log('endTime', endTime)
      if (startTime && endTime) {
        dailogform.startTime = startTime
        dailogform.endTime = endTime
      } else {
        dailogform.startTime = null
        dailogform.endTime = null
      }
      if (startTime) {
        const rows = await api.Holiday.getSearch({
          userName: currentUser.username,
          yearNum: formatDate(new Date(startTime), 'yyyy'),
          holidayCategory: dailogform.leaveCategory,
        })
        if (rows.length == 0) return
        const { holidayUsedNum, holidayNum, holidayBalanceNum, yearWarnNum } = rows[0]

        // 判断请假时长是否超出年假或调休假额度
        if (dailogform.leaveCategory == '0' || dailogform.leaveCategory == '1') {
          // 年假，调休
          // 当前请假时长 + 已使用时长 > 本年时长 + 去年余额
          flag1.value = dailogform.durationTime + holidayUsedNum > holidayNum + holidayBalanceNum
          flag1ErrorMessage.value = flag1.value ? '可用日期超了' : ''
        } else if (dailogform.leaveCategory == '2') {
          // 事假
          // 年 10
          // yearWarnNum = 10
          // 当前请假时长 + 已使用时长 >= 最长时长。
          flag2.value = dailogform.durationTime + holidayUsedNum > yearWarnNum
          flag2ErrorMessage.value = flag2.value ? `年度累计时长超过达到 ${yearWarnNum} 天，需要提交书面说明。` : ''
        } else if (dailogform.leaveCategory == '3') {
          // 病假
          // 年 15
          // 月 5
          // yearWarnNum = 15
          // 当前请假时长 + 已使用时长 >= 最长时长。
          flag2.value = dailogform.durationTime + holidayUsedNum > yearWarnNum
          flag2ErrorMessage.value = flag2.value ? `年度累计时长超过 ${yearWarnNum} 天，需要提交书面说明。` : ''
        }
        // 触发表单的 durationTime 字段验证，确保前端校验逻辑执行。
        ruleFormRef.value?.validateField('durationTime', () => {})

        // console.log('yearWarnNum', yearWarnNum)
        // console.log('flag1', flag1.value)
        // console.log('flag1ErrorMessage', flag1ErrorMessage.value)
      }
    }
  }
)

onMounted(() => {})

defineExpose({
  openDialog,
})
</script>
<style lang="scss" scoped>
.btn-category {
  height: auto;

  .cell {
    .icon {
      height: 60px;
      width: 60px;
      display: flex;
      justify-content: center;
      align-items: center;
    }
    .text {
      margin-top: 10px;
      text-align: center;
    }
  }
}
</style>
